package com.xdf.ecommerce.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.common.utils.CollectionUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * @author chanchaw
 * @create 2025-10-18 7:33
 */
@RequiredArgsConstructor
@Slf4j
@Component
@DependsOn({"gatewayConfig"}) // 依赖配置类GatewayConfig的Bean，在它之后加载
public class DynamicRouteServiceImpl8Nacos {
    private final GatewayConfig gatewayConfig;
    private ConfigService configService;
    private final DynamicRouteServiceImpl dynamicRouteService;

    /**
     * 根据配置类 GatewayConfig 创建 nacos 配置对象
     * @return
     */
    private ConfigService initConfigService(){
        try{
            Properties properties = new Properties();
            log.info("网关配置，serverAddr:[{}],namespace:[{}]",gatewayConfig.NACOS_SERVER_ADDR,gatewayConfig.NACOS_NAMESPACE);
            properties.setProperty("serverAddr",gatewayConfig.NACOS_SERVER_ADDR);
            properties.setProperty("namespace",gatewayConfig.NACOS_NAMESPACE);
            ConfigService ret = NacosFactory.createConfigService(properties);
            return ret;
        }catch (Exception ex){
            log.error("网关中初始化nacos配置出现异常：[{}]",ex.getMessage(),ex);
            return null;
        }
    }

    @PostConstruct
    public void init(){
        log.info("开始初始化网关路由...");
        try{
            configService = initConfigService();
            if(configService == null){
                log.error("由于初始化nacos配置失败导致初始化路由失败！");
                return;
            }
            String configInfo = configService.getConfig(gatewayConfig.NACOS_ROUTE_DATA_ID,gatewayConfig.NACOS_ROUTE_GROUP,GatewayConfig.DEFAULT_TIMEOUT);
            log.info("即将更新路由：[{}]",configInfo);
            List<RouteDefinition> definitionList = JSON.parseArray(configInfo, RouteDefinition.class);
            if(CollectionUtils.isNotEmpty(definitionList)){
                definitionList.forEach(item -> {
                    log.info("初始化路由：[{}]", item.toString());
                    dynamicRouteService.addRouteDefinition(item);
                });
            }
        }catch(Exception ex){
            log.error("网关初始化路由出现异常：[{}]",ex.getMessage(),ex);
        }
        // 添加监听器，nacos中路由变动会下发给本网关
        dynamicRouteByNacosListener(gatewayConfig.NACOS_ROUTE_DATA_ID,gatewayConfig.NACOS_ROUTE_GROUP);
    }

    private void dynamicRouteByNacosListener(String dataId, String group){
        try{
            configService.addListener(dataId, group, new Listener() {
                // nacos提供自定义线程池的方法，一般使用nacos默认的线程池
                @Override
                public Executor getExecutor() {
                    return null;
                }
                // 监听到配置更新
                @Override
                public void receiveConfigInfo(String configInfo) {
                    log.info("接受到nacos下的更新的配置：[{}]",configInfo);
                    List<RouteDefinition> definitionList = JSON.parseArray(configInfo,RouteDefinition.class);
                    log.info("JSON反序列化得到路由：[{}]", definitionList.toString());
                    dynamicRouteService.updateList(definitionList);
                }
            });
        }catch(Exception ex){
            log.error("网关中通过监听器更新路由出现异常：[{}]", ex.getMessage(),ex);
        }

    }
}
